package com.os.opencv.java.chapter13;

import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgproc.Imgproc;
import org.opencv.video.Video;
import org.opencv.videoio.VideoCapture;

import java.util.LinkedList;
import java.util.List;

public class MeanShift {

    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        //创建videocapture对象并打开视屏文件
        VideoCapture vc = new VideoCapture();
        vc.open("pics/2023-11-29_19-50-14.mp4");
        //确认视屏是否打开成功
        if(!vc.isOpened()){
            System.out.println("unable to load video");
            return;
        }

        //读取视屏的第一帧
        Mat frame = new Mat();
        vc.read(frame);

        //设置跟踪窗口
        Rect trackWindow = new Rect(350,190,100,100);
        Mat roi = new Mat(frame, trackWindow);
        Mat hsv0 = new Mat();
        Mat mask = new Mat();

        //转换为hsv颜色空间
        Imgproc.cvtColor(roi, hsv0, Imgproc.COLOR_BGR2HSV);
        Core.inRange(hsv0, new Scalar(0,60,32), new Scalar(180,255,255), mask);

        //直方图函数参数
        MatOfFloat range = new MatOfFloat(0,2565);
        Mat hist = new Mat();
        MatOfInt histSize = new MatOfInt(180);
        MatOfInt channels = new MatOfInt(0);

        //直方图数据统计并归一化
        List<Mat> mat0 = new LinkedList<>();
        mat0.add(hsv0);
        Imgproc.calcHist(mat0, channels, mask, hist, histSize, range);
        Core.normalize(hist, hist, 0, 255, Core.NORM_MINMAX);

        //设置终止条件
        TermCriteria criteria = new TermCriteria(TermCriteria.EPS | TermCriteria.COUNT, 10, 1);

        List<Mat> mat = new LinkedList<>();
        Mat hsv = new Mat();
        mat.add(hsv);

        while(true){
            //读取一帧视屏
            vc.read(frame);
            //如果视屏读取完毕则退出循环
            if(frame.empty()){
                break;
            }

            //计算目标区域的直方图反向投影
            Imgproc.cvtColor(frame, hsv, Imgproc.COLOR_BGR2HSV);
            Mat dst = new Mat();
            Imgproc.calcBackProject(mat, channels, hist, dst, range, 1);

            //meanshift跟踪目标
            Video.meanShift(dst, trackWindow, criteria);

            //绘制跟踪区域
            Point pt1 = new Point(trackWindow.x, trackWindow.y);
            Point pt2 = new Point(trackWindow.x + trackWindow.width, trackWindow.y + trackWindow.height);
            Imgproc.rectangle(frame, pt1, pt2, new Scalar(255,0,0), 2);

            //在屏幕上显示跟踪结果
            HighGui.imshow("frame", frame);
            int keyBoard = HighGui.waitKey(90);

            //如按esc键退出
            if(keyBoard == 27){
                break;
            }
        }
        System.exit(0);
    }
}
